use crate::field::{VddFieldRef, VddFieldType};
use crate::i18n_text::E_UNKNOWN_CODE;
use crate::id_factory::ID_FACTORY;
use crate::model::VddSchema;
use crate::query::VddValueEvaluation;
use crate::record::RecordRuleDetail::{RrConsumeTimes, RrFitEvaluation, RrUnique};
use crate::value::{VddValue, VddValueRef};
use crate::visit::{ShareRuleOfField, VisitGroup, VisitGroupType};
use crate::{
    datetime_format, i18n, Ares, Astr, FieldId, RecordId, UserId, CACHE_LISTENER, DT_FORMAT,
    EMPTY_FID,
};
use chrono::{Local, NaiveDateTime};
use rsa::RsaPublicKey;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use std::collections::HashMap;
use std::sync::Arc;

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecordMeta {
    pub id: RecordId,
    pub model_id: u64,
    pub uid: UserId,
    #[serde(with = "datetime_format")]
    pub update_ts: NaiveDateTime,
}

impl RecordMeta {
    pub fn new(uid: UserId, model_id: u64) -> Self {
        Self {
            id: RecordId(ID_FACTORY.lock().unwrap().lazy_generate()),
            model_id,
            uid,
            update_ts: Local::now().naive_local(),
        }
    }
    /// 从网关提交的数据中形成记录
    pub fn from_json(
        vg: &VisitGroup,
        j: &Value,
        code_field_map: &HashMap<Astr, VddFieldRef>,
    ) -> Result<Self, Astr> {
        let mut err_str = String::new();
        code_field_map.iter().for_each(|x| {
            let node = j.get(x.0.to_string());
            if node.is_none() {
                err_str.push_str(&format!("消息中无法找到需要的字段标记 {}\n", x.0));
                return;
            }
            let field = code_field_map.get(x.0);
            if field.is_none() {
                err_str.push_str(&format!("无法根据标记 {} 找到对应字段\n", x.0));
                return;
            }
        });
        if !err_str.is_empty() {
            Err(Arc::from(err_str))
        } else {
            Ok(Self {
                id: RecordId(ID_FACTORY.lock().unwrap().lazy_generate()),
                model_id: vg.model_id,
                uid: vg.u_id.clone(),
                update_ts: Local::now().naive_local(),
            })
        }
    }
    pub fn on_change(&mut self) {
        self.update_ts = Local::now().naive_local();
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "T", content = "C")]
pub enum RecordRuleDetail {
    #[serde(rename_all = "camelCase")]
    RrUnique(Vec<FieldId>),
    #[serde(rename_all = "camelCase")]
    // 该模型内记录的使用限制
    RrConsumeTimes {
        consumer_m_id: u64, // 链接到此模型的模型ID
        max: usize,
    },
    #[serde(rename_all = "camelCase")]
    RrFitEvaluation(Arc<VddValueEvaluation>),
}

pub const RR_UNIQUE: &'static str = "RrUnique";
pub const RR_CONSUME: &'static str = "RrConsumeTimes";
pub const RR_EVA: &'static str = "RrFitEvaluation";

impl TryFrom<&Value> for RecordRuleDetail {
    type Error = Astr;

    fn try_from(value: &Value) -> Result<Self, Self::Error> {
        let t = value["T"].as_str().unwrap();
        match t {
            RR_UNIQUE => {
                let field_ids = value["ids"].as_array().map(|fids| {
                    fids.iter()
                        .map(|fid| FieldId(fid.as_u64().unwrap()))
                        .collect::<Vec<FieldId>>()
                });
                Ok(RrUnique(field_ids.unwrap()))
            }
            RR_CONSUME => {
                let lm_id = value["mid"].as_u64().unwrap();
                let max = value["max"].as_u64().unwrap_or(0) as usize;
                Ok(RrConsumeTimes {
                    consumer_m_id: lm_id,
                    max,
                })
            }
            RR_EVA => Ok(RrFitEvaluation(
                VddValueEvaluation::try_from(value).unwrap().into(),
            )),
            _ => panic!("not implemented code for RecordValueRuleDetail"),
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecordRule {
    pub model_id: u64,
    pub id: u64,
    pub detail: Arc<RecordRuleDetail>,
}

impl RecordRule {
    pub fn new(model_id: u64, j: &Value) -> Self {
        Self {
            model_id,
            id: ID_FACTORY.lock().unwrap().lazy_generate(),
            detail: RecordRuleDetail::try_from(j).unwrap().into(),
        }
    }
    /// 判断这个规则是否包含某一字段
    pub fn has_fid(&self, f_id: &FieldId) -> bool {
        match self.detail.as_ref() {
            RrUnique(fids) => fids.contains(f_id),
            RrConsumeTimes { .. } => false,
            RrFitEvaluation(fve) => &fve.get_field_id() == f_id,
        }
    }
    /// 判断这个规则是否是组合唯一键规则
    pub fn rvrd_unique(&self) -> bool {
        match self.detail.as_ref() {
            RrUnique(_) => true,
            _ => false,
        }
    }
    /// 获取参与的字段ID集合
    pub fn get_fids(&self) -> Vec<FieldId> {
        match self.detail.as_ref() {
            RrUnique(fids) => fids.clone(),
            RrConsumeTimes { .. } => Vec::<FieldId>::new(),
            RrFitEvaluation(fve) => vec![fve.get_field_id().clone()],
        }
    }

    /// 判断一个值规则是针对某个消费模型的消费规则
    pub fn consume_by_model(&self, model_id: u64) -> bool {
        match self.detail.as_ref() {
            RrConsumeTimes { consumer_m_id, .. } => *consumer_m_id == model_id,
            _ => false,
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VddRecord {
    pub meta: Arc<RecordMeta>,
    pub value: HashMap<FieldId, VddValueRef>,
}

impl VddRecord {
    pub fn new_default(uid: UserId, model_id: u64) -> Self {
        Self {
            meta: Arc::new(RecordMeta::new(uid, model_id)),
            value: HashMap::<FieldId, VddValueRef>::new(),
        }
    }
    pub fn from_json(
        vg: &VisitGroup,
        j: &Value,
        code_field_map: &HashMap<Astr, VddFieldRef>,
    ) -> Result<Self, Astr> {
        let meta = RecordMeta::from_json(vg, j, code_field_map)?;
        let mut record_value_map = HashMap::<FieldId, VddValueRef>::new();
        let mut err_str = String::new();
        code_field_map.iter().for_each(|x| {
            let node = j.get(x.0.to_string());
            if node.is_none() {
                err_str.push_str(&format!("消息中无法找到需要的字段标记 {}\n", x.0));
                return;
            }
            let field = code_field_map.get(x.0);
            if field.is_none() {
                err_str.push_str(&format!("无法根据标记 {} 找到对应字段\n", x.0));
                return;
            }
            let field = field.unwrap();
            let node = node.unwrap();
            record_value_map.insert(
                field.id.clone(),
                Arc::new(VddValue::from_json(&field, &node, &vg.u_id)),
            );
        });
        if !err_str.is_empty() {
            Err(Arc::from(err_str))
        } else {
            Ok(Self {
                meta: Arc::new(meta),
                value: record_value_map,
            })
        }
    }
    ///
    pub fn clean_values(&mut self) {
        self.value.clear();
    }
    ///
    pub fn delete_value(&mut self, field_id: &FieldId) {
        self.value.remove(&field_id);
    }
    ///
    pub fn to_json(&self, tags: &HashMap<u64, Astr>, is_mine: bool) -> Value {
        let mut record_map = HashMap::<&str, Astr>::new();
        if is_mine {
            record_map.insert("_id", self.meta.id.0.to_string().into());
            record_map.insert(
                "_uts",
                self.meta.update_ts.format(DT_FORMAT).to_string().into(),
            );
            // let binding = self.uid.to_string();
            // record_map.insert("editor", binding.as_str());
        }
        self.value.iter().for_each(|x| {
            if tags.get(&x.0 .0).is_some() {
                // 传入的code_map可以不包含所有的字段码,根据所需要的字段返回值，不需要的字段不返回值
                record_map.insert(tags.get(&x.0 .0).unwrap(), x.1.get_simple_display());
            }
        });
        json!(record_map)
    }
    /// 共享的记录需要适应分享规则中的字段详细设置
    pub fn check_share_field(&mut self, group: &VisitGroup) -> Result<(), Astr> {
        group.rule_f.iter().for_each(|x| match x.as_ref() {
            ShareRuleOfField::SrfRo(field_ids) | ShareRuleOfField::SrfHide(field_ids) => {
                for fid in field_ids {
                    self.value.remove(&fid);
                }
            }
            _ => {}
        });
        Ok(())
    }
    /// 读取json内容,填充到record中
    pub fn update_form_json(
        &mut self,
        j: &Value,
        field_map: &HashMap<FieldId, VddFieldRef>,
        operator: &UserId,
    ) {
        if j["fields"].is_array() {
            for x in j["fields"].as_array().unwrap().iter() {
                let field_id = x["fieldId"].as_u64().unwrap();
                if let Some(field) = field_map.get(&FieldId(field_id)) {
                    self.value.insert(
                        FieldId(field_id),
                        Arc::new(VddValue::from_json(&field, &x["value"], operator)),
                    );
                }
            }
        }
    }
    /// 读取json内容,填充到record中, 返回被修改的字段原值
    pub fn update_form_json_with_vg(
        &mut self,
        j: &Value,
        field_map: &HashMap<FieldId, VddFieldRef>,
        vg: &VisitGroup,
        operator: &UserId,
    ) -> HashMap<FieldId, VddValueRef> {
        let mut old_fv_map = HashMap::<FieldId, VddValueRef>::new();
        let mut ro_field_ids = vg.hide_field_ids();
        ro_field_ids.append(&mut vg.ro_field_ids());
        if j["fields"].is_array() {
            for x in j["fields"].as_array().unwrap().iter() {
                let field_id = x["fieldId"].as_u64().unwrap();
                let field_id = FieldId(field_id);
                if ro_field_ids.contains(&field_id) {
                    continue; // 隐藏或者只读的值记录不修改
                }
                old_fv_map.insert(field_id.clone(), self.get_value(&field_id).clone());
                if let Some(field) = field_map.get(&field_id) {
                    self.value.insert(
                        field_id,
                        Arc::new(VddValue::from_json(&field, &x["value"], operator)),
                    );
                }
            }
        }
        old_fv_map
    }
    /// 获取值
    pub fn get_value(&self, field: &FieldId) -> VddValueRef {
        let r = self.value.get(field);
        if r.is_none() {
            Arc::new(VddValue::NULL)
        } else {
            r.unwrap().clone()
        }
    }
    ///
    pub fn set_id(&mut self, rid: &RecordId) {
        Arc::get_mut(&mut self.meta).unwrap().id = rid.clone();
    }

    /// 判断一条记录是否符合字段值过滤条件
    pub fn fit_evaluation(&self, fve: &VddValueEvaluation) -> bool {
        let fv = self.get_value(&fve.get_field_id());
        fve.evaluate(&fv)
    }

    /// 判断一笔记录是否符合访问规则，读取时专用，判断一笔记录是否能放进结果集
    pub fn fit_vg(
        &self,
        vg: &VisitGroup,
        model_owner_id: &UserId,
        visitor_id: &UserId,
    ) -> Result<(bool, bool), Astr> {
        if model_owner_id == visitor_id || self.meta.uid == visitor_id.clone() {
            return Ok((true, true));
        }
        let mut can_edit: bool = false;
        let mut can_delete: bool = false;
        match vg.group_type.as_ref() {
            VisitGroupType::VgtAnonymous => Ok((false, false)),
            VisitGroupType::VgtPubKey | VisitGroupType::VgtCode { .. } => {
                let mut can_see = false;
                // 看这个记录是否在访问权力允许范围内
                for right in vg.rule_m.iter() {
                    let check_result =
                        right.fit_record(self, model_owner_id.clone(), visitor_id.clone());
                    if let Ok(cr) = check_result {
                        can_see = true;
                        can_edit = cr.0;
                        can_delete = cr.1;
                        break;
                    }
                }
                // 看这个记录是否满足所有查询条件
                if can_see {
                    for x in vg.rule_fv.iter() {
                        if !self.fit_evaluation(&x) {
                            can_see = false;
                            break;
                        }
                    }
                }
                if !can_see {
                    Err("记录超出允许访问的范围".into())
                } else {
                    Ok((can_edit, can_delete))
                }
            }
            VisitGroupType::VgtVirtualAuthor => Ok((true, true)),
        }
    }

    /// 根据访问组里的修改性限定修改记录
    pub fn change_by_vg_for_read(
        &mut self,
        vgls: &[Arc<ShareRuleOfField>],
        visitor_pub_key: &RsaPublicKey,
    ) -> Ares {
        // 隐藏限定列值
        for x in vgls.iter() {
            match x.as_ref() {
                ShareRuleOfField::SrfHide(f_ids) => {
                    f_ids.iter().for_each(|f_id| {
                        self.value.remove(f_id);
                    });
                }
                ShareRuleOfField::SrfEnc(f_ids) => f_ids.iter().for_each(|f_id| {
                    let fv = self.get_value(f_id);
                    let v_e = fv.encrypt_to_b64(visitor_pub_key);
                    self.value
                        .insert(f_id.clone(), VddValue::EncryptedB64(v_e).into());
                }),
                _ => {}
            }
        }
        Ok(())
    }

    /// 判断一笔记录是否符合访问规则，以便添加或修改
    pub fn change_by_vg_for_write(
        &mut self,
        vg: &VisitGroup,
        is_edit: bool,
        old_fvs: HashMap<FieldId, VddValueRef>,
    ) -> Result<(), Astr> {
        // 将限制修改的字段恢复原值
        if is_edit {
            for x in vg.rule_f.iter() {
                match x.as_ref() {
                    ShareRuleOfField::SrfHide(field_ids) | ShareRuleOfField::SrfRo(field_ids) => {
                        field_ids.iter().for_each(|y| {
                            if old_fvs.contains_key(y) {
                                self.value
                                    .insert(y.clone(), old_fvs.get(y).unwrap().clone());
                            }
                        });
                    }
                    ShareRuleOfField::SrfEnc(_) => {
                        // TODO
                    }
                }
            }
        }
        Ok(())
    }
    /// 判断此记录是否属于某个用户
    pub fn belong_to(&self, u_id: &UserId) -> bool {
        &self.meta.uid == u_id
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VersionedRecord {
    pub version: u64,
    pub record_id: RecordId,
    pub value: HashMap<FieldId, VddValueRef>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VddDisplay {
    pub meta: Arc<RecordMeta>,
    pub value: HashMap<FieldId, VddValueRef>,
    pub display: HashMap<FieldId, Astr>,
}

impl VddDisplay {
    pub fn from(record: Arc<VddRecord>) -> Self {
        let mut r = Self {
            meta: record.meta.clone(),
            value: record.value.clone(),
            display: HashMap::<FieldId, Astr>::new(),
        };
        r.value.iter().for_each(|(fid, fv)| {
            r.display.insert(fid.clone(), fv.get_simple_display());
        });
        r
    }
    ///
    pub fn meta_to_display(&mut self) {
        self.set_display(&EMPTY_FID, &self.meta.id.0.to_string());
        self.set_display(
            &FieldId(1),
            &self.meta.update_ts.format(DT_FORMAT).to_string(),
        );
        self.set_display(&FieldId(2), &self.meta.uid.0.to_string());
    }
    ///
    pub fn set_display(&mut self, field_id: &FieldId, display: &str) {
        self.display.insert(field_id.clone(), Arc::from(display));
    }
    /// 获取记录中某个字段的展示字符串
    pub fn get_display(&self, field_id: &FieldId) -> Astr {
        self.get_value(&field_id).get_simple_display()
    }
    /// 生成代码表字段展现的内容
    pub fn fill_display_801(&mut self, schema: &VddSchema) {
        for field in schema.fields.iter() {
            if let VddFieldType::FtCode(code_source) = field.field_type.as_ref() {
                let j = serde_json::from_str::<Value>(code_source).unwrap();
                let codes = j.as_array().unwrap();
                if let Some(fv) = self.value.to_owned().get(&field.id) {
                    match fv.as_ref() {
                        VddValue::S801(v) => {
                            codes.iter().for_each(|x| {
                                if x["c"].as_str().is_some() && x["c"].as_str().unwrap() == v {
                                    self.set_display(&field.id, x["l"].as_str().unwrap());
                                }
                            });
                            if !self.display.contains_key(&field.id) {
                                self.set_display(&field.id, i18n!(E_UNKNOWN_CODE).as_ref());
                            }
                        }
                        VddValue::M801(v) => {
                            let mut displays = Vec::<String>::new();
                            v.iter().for_each(|x| {
                                let mut found = false;
                                codes.iter().for_each(|y| {
                                    if y["c"].as_str().is_some() && y["c"].as_str().unwrap() == x {
                                        displays.push(y["l"].as_str().unwrap().to_string());
                                        found = true;
                                    }
                                });
                                if !found {
                                    displays.push(i18n!(E_UNKNOWN_CODE).to_string());
                                }
                            });
                            self.set_display(&field.id, &json!(displays).to_string());
                        }
                        _ => {}
                    }
                }
            }
        }
    }
    /// 通过一批字段获取字段值
    pub fn values_by_fields(&self, fields: &[VddFieldRef]) -> Vec<VddValueRef> {
        let mut values = Vec::<VddValueRef>::new(); // 要比较的值
        fields.iter().for_each(|x| {
            values.push(self.get_value(&x.id).clone());
        });
        values
    }
    /// 从带有展示属性的记录中获取字段值
    pub fn get_value(&self, fid: &FieldId) -> VddValueRef {
        let fv = self.value.get(fid);
        if let Some(fv) = fv {
            fv.to_owned()
        } else {
            VddValue::NULL.into()
        }
    }
    ///
    pub fn record(&self) -> Arc<VddRecord> {
        let r = VddRecord {
            meta: self.meta.clone(),
            value: self.value.clone(),
        };
        Arc::new(r)
    }
}

/// 回收站里的记录
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct VddRecordInTrash {
    pub record_id: RecordId,
    pub value: HashMap<FieldId, VddValueRef>,
}

/// 一条记录在其他模型中被使用的记录
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecordConsume {
    pub record_id: RecordId,
    pub consumer_m_id: u64,
    pub consumer_f_id: FieldId,
    pub consumer_r_id: RecordId,
}

/// 记录更新订阅
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecordSubscriber {
    pub model_id: u64,
    pub subscriber: UserId,
    #[serde(with = "datetime_format")]
    pub cts: NaiveDateTime,
}

impl RecordSubscriber {
    pub fn new(model_id: u64, subscriber: UserId) -> Self {
        let cts = if subscriber == CACHE_LISTENER {
            NaiveDateTime::default()
        } else {
            Local::now().naive_local()
        };
        Self {
            model_id,
            subscriber,
            cts,
        }
    }
    pub fn reset(&mut self) {
        self.cts = Local::now().naive_local();
    }
}

/// 记录变更事件
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecordChangeEvent {
    pub id: u64,
    pub ts: NaiveDateTime,
    pub action: u8,
    pub rid: RecordId,
}
